<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Controller;

use App\Amqp\Producer\DemoProducer;
use App\Constants\ErrorCode;
use App\Constants\SuccessCode;
use App\Model\Novel;
use App\Model\User;
use App\Request\IndexRequest;
use App\Service\queue\QueueService;
use App\Task\MongoTask;
use App\Utils\Modbus\ModbusRtu;
use App\Utils\Modbus\ModbusRtuOrTcp;
use App\Utils\Modbus\ModbusTcp;
use App\Utils\Music\Meting;
use hg\apidoc\annotation as Apidoc;
use Hyperf\Amqp\Producer;
use Hyperf\Context\ApplicationContext;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Di\Exception\Exception;
use Hyperf\HttpServer\Annotation\AutoController;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Qbhy\HyperfAuth\AuthManager;
use QL\QueryList;

#[AutoController]
#[Apidoc\Title('首页')]
#[Apidoc\Group('index')]
class IndexController extends AbstractController
{

    #[Inject]
    protected QueueService $redis_queue_service;

    //授权登录信息.生成JWT
    #[Inject]
    protected AuthManager $authManager;


    #[Inject]
    protected Meting $meting;

    //#[Inject]
    //private ClientFactory $clientFactory;
//    #[Inject]
//    protected ValidatorFactoryInterface $validationFactory;
    #[
        Apidoc\Title('首页信息'),
        Apidoc\Method('GET'),
        Apidoc\Url('/index'),
        Apidoc\Query(name: 'ip', type: 'string', require: true,default: "222.212.14.71", desc: 'IP地址'),
        Apidoc\Returned('id', type: 'int', desc: '信息id'),
    ]
    public function index(IndexRequest $indexRequest)
    {
        $validated = $indexRequest->validated();
        //手动验证器验证
//        $validator = $this->validationFactory->make(
//            $this->request->all(),
//            [
//                'ip' => 'required|ip',
//            ]
//        );
//        if ($validator->fails()){
//            $errorMessage = $validator->errors()->first();
//            return $this->error($errorMessage);
//        }
//        $ip_add = $this->ip2region->binarySearch($this->request->input('ip'));
        try {
            $ip_add = $this->ip2region->binarySearch($validated['ip']);
        } catch (Exception $e) {
            return $this->error($e->getMessage());
        }
        //$user = $this->request->input('user', 'Hyperf');
        //$method = $this->request->getMethod();

        return $this->success($ip_add);
    }

    #[
        Apidoc\Title('task'),
        Apidoc\Method('GET'),
        Apidoc\Url('/index/MongoTask'),
    ]
    public function MongoTask():ResponseInterface
    {
        try {
            $client = ApplicationContext::getContainer()->get(MongoTask::class);
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
            return $this->error($e->getMessage());
        }
        $client->insert('hyperf.test', ['id' => rand(0, 99999999)]);

        $result = $client->query('hyperf.test', [], [
            'sort' => ['id' => -1],
            'limit' => 5,
        ]);
        return $this->success($result);
    }

    #[
        Apidoc\Title('抓取'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'url', type: 'string', require: true,default: "https://www.xs8.cn/chapter/14445259705210704/41559391593803490", desc: 'url地址'),
        Apidoc\Url('/index/get_http_pool'),
    ]
    public function get_http_pool()
    {
        $url = $this->request->input('url',"https://www.xs8.cn/chapter/14445259705210704/41559391593803490");

        $data_query = QueryList::get($url);
        $rt = [];
        // DOM解析文章标题
//        $names = $data_query->find('.volume-wrap>.volume>.cf>li>a')->texts();
//        // DOM解析文章作者
//        $urls = $data_query->find('.volume-wrap>.volume>.cf>li>a')->attrs('href');
//        $new_array=[];
//        $count = count($names);
//        for ($i=0;$i<$count;$i++){
//            $new_array[]=['name'=>$names[$i],'url'=>$urls[$i]];
//        }

        //内容解析
        $connect_number = $data_query->find('.info>i:eq(0)>.j_chapterWordCut')->text();
        $connect_time = $data_query->find('.info>i:eq(1)>.j_updateTime')->text();
        $connect = $data_query->find('.j_readContent>.ywskythunderfont>p')->text();
        $strlen = strlen($connect);
        $new_connect = substr($connect,0,strrpos($connect ,"window.fkp"));
        //$client = $this->clientFactory->create();
        //$data = $client->get($url)->getBody()->getContents();
        //$data=  http_pool_curl($url);
        return $this->success([$connect_number,$connect_time,$connect,$new_connect,$strlen]);
    }

    #[
        Apidoc\Title('获取小说内容'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'id', type: 'int', require: true,default: "1", desc: '小说id'),
        Apidoc\Query(name: 'page', type: 'int', require: true,default: "1", desc: '页数'),
        Apidoc\Query(name: 'page_size', type: 'int', require: true,default: "20", desc: '数量'),
        Apidoc\Url('/index/get_novel'),
    ]
    public function get_novel(): ResponseInterface
    {
        $id = $this->request->input('id',1);
        $page = $this->request->input('page',1);
        $page_size = $this->request->input('page_size',20);
        $data = Novel::with(['getNovelChapterLists'=>function ($query)use($page,$page_size) {
            $offset = $page*$page_size;
            return $query->select(['id','novel_id','chapter_number','name','url','content','number_words','is_complete'])->offset($offset)->limit($page_size)->get();
        }])->select(['id','classify','author','name','url','brief_introduction','img','overall_novel','number_words'])->where('id',$id)->get();
        return $this->success($data);
    }


    #[
        Apidoc\Title('modbus获取数据'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'host', type: 'string', require: true,default: "127.0.0.1", desc: '远程服务器的地址'),
        Apidoc\Query(name: 'port', type: 'int', require: true,default: "501", desc: '远程服务器端口'),
        Apidoc\Query(name: 'address', type: 'int', require: true,default: "1", desc: '寄存器地址'),
        Apidoc\Query(name: 'name', type: 'string', require: true,default: "name", desc: '寄存器地址对应的字段'),
        Apidoc\Query(name: 'timeout', type: 'string', require: true,default: "0.5", desc: '网络 IO 的超时时间'),
        Apidoc\Url('/index/get_modbus'),
    ]
    public function get_modbus()
    {
        $host = (string)$this->request->input('host');
        $name = (string)$this->request->input('name');
        $port = (int)$this->request->input('port');
        $address = (int)$this->request->input('address');
        $timeout = (float)$this->request->input('timeout');
        $modbus_tcp = new ModbusTcp($host,$port,$timeout);
        $data = $modbus_tcp->getValue($address,$name);
        if (is_string($data)){
            return $this->error($data);
        }
        return $this->success($data);
    }


    #[
        Apidoc\Title('RabbitMQ数据写入对列'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'name', type: 'string', require: true,default: "张三", desc: '名称'),
        Apidoc\Query(name: 'value', type: 'string', require: true,default: "唐家三少", desc: '值'),
        Apidoc\Url('/index/get_rabbit'),
    ]
    public function get_rabbit()
    {
        try {
            $data = $this->request->all();
            $message = new DemoProducer($data);
            $producer = ApplicationContext::getContainer()->get(Producer::class);
            $result = $producer->produce($message);
            return $this->success([$result]);
        }catch (\Exception $exception){
            return $this->error($exception->getMessage());
        }
    }
    #[
        Apidoc\Title('RedisQueue数据写入对列'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'name', type: 'string', require: true,default: "张三", desc: '名称'),
        Apidoc\Query(name: 'value', type: 'string', require: true,default: "唐家三少", desc: '值'),
        Apidoc\Url('/index/get_redis_queue'),
    ]
    //#[RateLimit(create: 2, consume: 2, capacity: 4)]
    public function get_redis_queue()
    {
        try {
            $data = $this->request->all();
           $this->redis_queue_service->push($data);
           return $this->success([$data]);
        }catch (\Exception $exception){
            return $this->error($exception->getMessage());
        }
    }

    #[
        Apidoc\Title('JWT登录模拟生成token'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'username', type: 'string', require: true,default: "admin", desc: '账号'),
        Apidoc\Query(name: 'password', type: 'string', require: true,default: "admin888", desc: '密码'),
        Apidoc\Query(name: 'token', type: 'string', require: true,default: "token", desc: '昵称'),
        Apidoc\Url('/index/get_login'),
    ]
    //#[RateLimit(create: 2, consume: 2, capacity: 4)]
    public function get_login()
    {
        try {
            //第一种方式
            //$auth = auth();
            //第二种方法,通过注解
            $auth = $this->authManager;
            //获取前端传过来的数据
            $data = $this->request->all();
            $user = User::query()->where(['username'=>$data['username']])->first();
            if (empty($user)){
                return $this->error(ErrorCode::USER_NOT_EXIST);
            }
            $get_token = $data['token']??"";
            if (empty($get_token)){
                return $this->error(ErrorCode::TOKEN_NOT_EMPTY);
            }
            //检查是否登录
            $status = $auth->guest();
            if ($status){
                return $this->error("已登录");
            }
            // 退出登录
            //$auth->logout();
            //获取token
            $token = $auth->guard('jwt')->login($user);
            $data_user['token'] = $token;
            $data_user['user'] = $auth->user($token);
            $data_user['user_id'] = $auth->id($token);
            $data_user['check'] = $auth->check($token);
            $data_user['guest'] = $auth->guest();
            return $this->success($data_user,SuccessCode::LOGIN_SUCCESS);
        }catch (\Exception $exception){
            return $this->error($exception->getMessage());
        }
    }

    #[
        Apidoc\Title('获取音乐'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'keyword', type: 'string', require: true,default: "admin", desc: '搜索音乐'),
        Apidoc\Url('/index/get_music'),
    ]
    public function get_music()
    {
        $data = $this->meting->format(true)->search('Soldier', [
            'page' => 1,
            'limit' => 50
        ]);
        return $this->success($data);
    }


    #[
        Apidoc\Title('获取开始值范围内的寄存器的值'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'host', type: 'string', require: true,default: "127.0.0.1", desc: '远程服务器的地址'),
        Apidoc\Query(name: 'port', type: 'int', require: true,default: "501", desc: '远程服务器端口'),
        Apidoc\Query(name: 'address', type: 'int', require: true,default: "1", desc: '寄存器地址'),
        Apidoc\Query(name: 'number', type: 'int', require: true,default: "10", desc: '数量长度'),
        Apidoc\Query(name: 'timeout', type: 'string', require: true,default: "0.5", desc: '网络 IO 的超时时间'),
        Apidoc\Url('/index/get_rtu'),
    ]
    public function get_rtu()
    {
        $host = (string)$this->request->input('host');
        $number = (int)$this->request->input('number');
        $port = (int)$this->request->input('port');
        $address = (int)$this->request->input('address');
        $timeout = (float)$this->request->input('timeout');
        $modbus_tcp = new ModbusTcp($host,$port,$timeout);
        $data = $modbus_tcp->getAddressList($address,$number);
        if (is_string($data)){
            return $this->error($data);
        }
        return $this->success($data,"操作成功");
    }


    #[
        Apidoc\Title('获取当前写入值的报文'),
        Apidoc\Method('GET'),
        Apidoc\Query(name: 'host', type: 'string', require: true,default: "127.0.0.1", desc: '远程服务器的地址'),
        Apidoc\Query(name: 'port', type: 'int', require: true,default: "501", desc: '远程服务器端口'),
        Apidoc\Query(name: 'address', type: 'int', require: true,default: "1", desc: '寄存器地址'),
        Apidoc\Query(name: 'value', type: 'int', require: true,default: "1", desc: '寄存器地址'),
        Apidoc\Query(name: 'number', type: 'int', require: true,default: "1", desc: '数量'),
        Apidoc\Query(name: 'dataType', type: 'string', require: true,default: "uint16", desc: '数据类型'),
        Apidoc\Query(name: 'timeout', type: 'string', require: true,default: "0.5", desc: '网络 IO 的超时时间'),
        Apidoc\Url('/index/get_modbus_message'),
    ]
    public function get_modbus_message()
    {
        $host = (string)$this->request->input('host');
        $number = (int)$this->request->input('number');
        $port = (int)$this->request->input('port');
        $address = (int)$this->request->input('address');
        $dataType = $this->request->input('dataType','uint16');
        $value = (int)$this->request->input('value','0');
        $timeout = (float)$this->request->input('timeout');
        $modbus_tcp = new ModbusTcp($host,$port,$timeout);
        $data = $modbus_tcp->getModbusReadMessage($address,'uint16',10);
        //$modbus_rtu = new ModbusRtu();
        //$data = $modbus_rtu->getValue($address,$number);
        //$modbus_tcp_rtu = new ModbusRtuOrTcp($host,$port,$timeout);
        //$data= $modbus_tcp_rtu->getAddressList($address,$number);
        //$modbus_rtu = new ModbusRtu('COM1');
        //$data = $modbus_rtu->getReadSerial(50,1,1);
        if (is_string($data)){
            return $this->error($data);
        }
        return $this->success($data,"操作成功");
    }


}
